package com.sojson.project.service.impl;

import java.io.IOException;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.ijpay.core.IJPayHttpResponse;
import com.ijpay.core.enums.RequestMethod;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.enums.WxApiType;
import com.ijpay.wxpay.enums.WxDomain;
import com.sojson.base.impl.BaseUser;
import com.sojson.constant.Constant;
import com.sojson.constant.ConstantCache;
import com.sojson.constant.ConstantMessageSystemTemplate;
import com.sojson.constant.IpConfig;
import com.sojson.constant.Lock;
import com.sojson.enums.EBalanceCount;
import com.sojson.enums.EBalanceDivideType;
import com.sojson.enums.EBalanceTotalType;
import com.sojson.enums.EBalanceType;
import com.sojson.enums.EFirstOrderType;
import com.sojson.enums.EMessageSystemType;
import com.sojson.enums.EOrderType;
import com.sojson.enums.core.EGeneralStatus;
import com.sojson.enums.core.EModuleNo;
import com.sojson.enums.core.EOrderCloseType;
import com.sojson.enums.core.EOrderStatus;
import com.sojson.enums.core.EPayStatus;
import com.sojson.enums.core.ERefundsStatus;
import com.sojson.enums.core.EUserCouponStatus;
import com.sojson.project.dao.AddressesDao;
import com.sojson.project.dao.BalanceLogDao;
import com.sojson.project.dao.CouponGoodsDao;
import com.sojson.project.dao.GoodSpecsDao;
import com.sojson.project.dao.GoodsDao;
import com.sojson.project.dao.OrderChildDao;
import com.sojson.project.dao.OrderDao;
import com.sojson.project.dao.OrderGoodsDao;
import com.sojson.project.dao.SpecsAttrDao;
import com.sojson.project.dao.SpecsCateDao;
import com.sojson.project.dao.UserCouponDao;
import com.sojson.project.entity.bo.CouponUseGoodsParam;
import com.sojson.project.entity.bo.CouponUseResponse;
import com.sojson.project.entity.bo.OrderGoodsParam;
import com.sojson.project.entity.bo.OrderParam;
import com.sojson.project.entity.bo.OrderStoreParam;
import com.sojson.project.entity.po.BalanceLog;
import com.sojson.project.entity.po.Brokerage;
import com.sojson.project.entity.po.GoodSpecs;
import com.sojson.project.entity.po.Goods;
import com.sojson.project.entity.po.Order;
import com.sojson.project.entity.po.OrderChild;
import com.sojson.project.entity.po.OrderGoods;
import com.sojson.project.entity.po.UserCoupon;
import com.sojson.project.entity.vo.OrderVo;
import com.sojson.project.service.BrokerageService;
import com.sojson.project.service.CouponService;
import com.sojson.project.service.MessageSystemService;
import com.sojson.project.service.OrderGoodsService;
import com.sojson.project.service.OrderService;
import com.sojson.project.sys.config.entity.vo.ConfigVo;
import com.sojson.project.sys.user.dao.UserDao;
import com.sojson.project.sys.user.entity.po.User;
import com.sojson.util.ArithUtil;
import com.sojson.util.DateUtil;
import com.sojson.util.ExpUtil;
import com.sojson.util.StringUtil;
import com.sojson.util.SystemParamUtil;
import com.sojson.util.id.IdUtil;
import com.sojson.util.json.JsonUtil;
import com.sojson.util.kd.kdn.KdnUtil;
import com.sojson.util.kd.kdn.bean.KdnParam;
import com.sojson.util.kd.kdn.bean.KdnResponse;
import com.sojson.util.pay.PayUtil;
import com.sojson.util.pay.bean.PayResult;
import com.sojson.util.pay.wx.WxUtil;
import com.sojson.util.pay.wx.bean.WxParamV3;
import com.sojson.util.pay.wx.bean.WxResponseV3;
import com.sojson.util.pay.wx.bean.WxResult;
import com.sojson.util.pay.wx.bean.child.param.WxPamAmount;
import com.sojson.util.pay.wx.constant.WxConstant;
import com.sojson.util.pay.wx.constant.WxCurrencyType;
import com.sojson.util.token.TokenUtil;

/**
 * 订单表Service实现类
 *
 * @author liu
 * @date 2021-03-16
 */
@Service
public class OrderServiceImpl implements OrderService {

    @Lazy
    @Autowired
    private OrderServiceImpl orderService;
    @Autowired
    private OrderChildDao orderChildDaoImpl;
    @Autowired
    private MessageSystemService messageSystemService;
    @Autowired
    private BrokerageService brokerageService;
    @Autowired
    private CouponService couponService;
    @Autowired
    private OrderGoodsService orderGoodsService;
    @Resource
    private OrderDao orderDaoImpl;
    @Resource
    private OrderGoodsDao orderGoodsDaoImpl;
    @Resource
    private UserCouponDao userCouponDaoImpl;
    @Resource
    private CouponGoodsDao couponGoodsDaoImpl;
    @Resource
    private GoodSpecsDao goodSpecsDaoImpl;
    @Resource
    private GoodsDao goodsDaoImpl;
    @Resource
    private AddressesDao addressesDaoImpl;
    @Resource
    private UserDao userDao;
    @Resource
    private BalanceLogDao balanceLogDaoImpl;
    @Resource
    private SpecsCateDao specsCateDaoImpl;
    @Resource
    private SpecsAttrDao specsAttrDaoImpl;

    /**
     * 单条插入
     *
     * @param order
     * @return
     * @throws SQLException
     */
    @Override
    public int insert(Order order) {
        int insert = orderDaoImpl.insert(order);
        return insert;
    }

    /**
     * 批量插入
     *
     * @param order
     * @return
     * @throws SQLException
     */
    @Override
    public int insertList(Order order) {
        int insertList = orderDaoImpl.insertList(order.getOrders());
        return insertList;
    }

    /**
     * 通过对象批量删除(物理删除)
     *
     * @param order
     * @return
     * @throws SQLException
     */
    @Override
    public int deleteByDto(Order order) {
        int deleteByDto = orderDaoImpl.deleteByDto(order);
        return deleteByDto;
    }

    /**
     * 统计全部数量
     *
     * @return
     * @throws SQLException
     */
    @Override
    public int countAll() {
        int countAll = orderDaoImpl.countAll();
        return countAll;
    }

    /**
     * 查询所有
     *
     * @return
     * @throws SQLException
     */
    @Override
    public List<Order> findAll() {
        List<Order> findAll = orderDaoImpl.listAll();
        return findAll;
    }

    /**
     * 根据对象统计数量
     *
     * @param order
     * @return
     * @throws SQLException
     */
    @Override
    public int countByDto(Order order) {
        int countByDto = orderDaoImpl.countByDto(order);
        return countByDto;
    }

    /**
     * 根据对象查询
     *
     * @param order
     * @return
     * @throws SQLException
     */
    @Override
    public List<Order> findByDto(Order order) {
        List<Order> findByDto = orderDaoImpl.listByDto(order);
        return findByDto;
    }

    /**
     * 通过id删除(物理删除)
     *
     * @param id
     * @return
     * @throws IOException
     * @throws SQLException
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public int deleteById(String id) throws IOException {
        int deleteById = 0;

        // 获取订单
        Order findById = orderDaoImpl.findById(id);
        if (StringUtil.isBlankObject(findById)) {
            return deleteById;
        }
        if (!findById.getUserNo().equals(TokenUtil.getUserId())) {
            ExpUtil.throwEx("只能删除自己的订单！");
        }

        // 判断订单是否可以删除
        // 已支付
        if (EPayStatus.YES.getCode() == findById.getIsPay()) {
            if (findById.getStatus() != EOrderStatus.RETU_YES.getCode()
                && findById.getStatus() != EOrderStatus.COMMENT_NO.getCode()
                && findById.getStatus() != EOrderStatus.CLOSE_YES.getCode()) {
                ExpUtil.throwEx("订单未完成，不能删除！");
            }
        }

        // 删除订单
        orderGoodsDaoImpl.deleteByOrderNo(findById.getNo());
        deleteById = orderDaoImpl.deleteById(id);
        return deleteById;
    }

    /**
     * 通过id列表删除(物理删除)
     *
     * @param ids
     * @return
     * @throws SQLException
     */
    @Override
    public int deleteByIdList(List<Integer> ids) {
        int deleteByIdList = orderDaoImpl.deleteByIdList(ids);
        return deleteByIdList;
    }

    /**
     * 通过id更新(全部更新)
     *
     * @param order
     * @return
     * @throws SQLException
     */
    @Override
    public int updateById(Order order) {
        int updateById = orderDaoImpl.updateById(order);
        return updateById;
    }

    /**
     * 通过id列表更新(全部更新)(更新内容相同)
     *
     * @param order
     * @return
     * @throws SQLException
     */
    @Override
    public int updateStaticByIdList(Order order) {
        int updateStaticByIdList = orderDaoImpl.updateStaticByIdList(order);
        return updateStaticByIdList;
    }

    /**
     * 通过id列表更新(全部更新)(更新内容不相同)
     *
     * @param order
     * @return
     * @throws SQLException
     */
    @Override
    public int updateChangeByIdList(Order order) {
        int updateChangeByIdList = orderDaoImpl.updateChangeByIdList(order.getOrders());
        return updateChangeByIdList;
    }

    /**
     * 通过id更新(局部更新)
     *
     * @param order
     * @return
     * @throws SQLException
     */
    @Override
    public int updatePartialById(Order order) {
        int updatePartialById = orderDaoImpl.updatePartialById(order);
        return updatePartialById;
    }

    /**
     * 通过订单号更新(局部更新)
     *
     * @param order
     * @return
     */
    @Override
    public int updatePartialByOrderNo(Order order) {
        int updatePartialByOrderNo = orderDaoImpl.updatePartialByOrderNo(order);
        return updatePartialByOrderNo;
    }

    /**
     * 通过id列表更新(局部更新)(更新内容相同)
     *
     * @param order
     * @return
     * @throws SQLException
     */
    @Override
    public int updateStaticPartialByIdList(Order order) {
        int updateStaticPartialByIdList = orderDaoImpl.updateStaticPartialByIdList(order);
        return updateStaticPartialByIdList;
    }

    /**
     * 通过id列表更新(局部更新)(更新内容不相同)
     *
     * @param order
     * @return
     * @throws SQLException
     */
    @Override
    public int updateChangePartialByIdList(Order order) {
        int updateChangePartialByIdList = orderDaoImpl.updateChangePartialByIdList(order.getOrders());
        return updateChangePartialByIdList;
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     * @throws SQLException
     */
    @Override
    public Order findById(String id) {
        Order findById = orderDaoImpl.findById(id);
        return findById;
    }

    /**
     * 通过id列表查询
     *
     * @param ids
     * @return
     * @throws SQLException
     */
    @Override
    public List<Order> findByIdList(List<Integer> ids) {
        List<Order> findByIdList = orderDaoImpl.findByIdList(ids);
        return findByIdList;
    }

    /**
     * 通过对象查询id列表
     *
     * @param order
     * @return
     * @throws SQLException
     */
    @Override
    public List<Integer> findIdByDto(Order order) {
        List<Integer> findIdByDto = orderDaoImpl.findIdByDto(order);
        return findIdByDto;
    }

    /**
     * 清空数据(物理清空)
     *
     * @throws SQLException
     */
    @Override
    public void clear() {
        orderDaoImpl.clear();
    }

    /**
     * 下单(购买)
     *
     * @param goods
     * @return
     * @throws Exception
     */

    @Override
    public String ordersBuy(OrderParam orderParam) throws Exception {
        String orders = null;
        List<OrderStoreParam> orderStoreParams = orderParam.getOrderStoreParams();

        synchronized (Lock.ORDER_STATUS) {
            orders = orderService.ordersBuyGo(orderParam, orderStoreParams);
        }
        return orders;
    }

    @Transactional(rollbackFor = Throwable.class)
    public String ordersBuyGo(OrderParam orderParam, List<OrderStoreParam> orderStores) throws Exception {
        String noShop = IdUtil.uuid();
        StringBuilder orders = new StringBuilder();

        for (OrderStoreParam orderStore : orderStores) {
            orders.append(orderService.ordersBuyGo(orderParam, orderStore, noShop)).append(",");
        }
        return orders.substring(0, orders.length() - 1);
    }

    @Transactional(rollbackFor = Throwable.class)
    public String ordersBuyGo(OrderParam orderParam, OrderStoreParam orderStoreParam, String noShop) throws Exception {
        Order order = new Order();
        // 订单编号
        String uuid = IdUtil.uuid();
        // 优惠券编号
        String couponNos = orderStoreParam.getCouponNos();
        BaseUser user = TokenUtil.getUser();

        // 获取收获地址
        // Addresses addresses = addressesDaoImpl.findById(orderParam.getAddressesId());
        // if (StringUtil.isBlankObject(addresses)) {
        // ExpUtil.throwEx("收获地址不存在！");
        // }
        order.insertInit();
        // order.setNoShop(noShop);
        order.setNo(uuid);
        order.setUserNo(user.getId());
        order.setCouponNos(couponNos);
        order.setIsShop(orderParam.getIsShop());
        order.setConsignee(orderParam.getName());
        order.setMobile(orderParam.getMobile());
        order.setTypeDelivery(orderStoreParam.getTypeDelivery());
        order.setProvince(orderParam.getProvince());
        order.setCity(orderParam.getCity());
        order.setArea(orderParam.getArea());
        order.setAddress(orderParam.getAddress());
        order.setMark(orderStoreParam.getMark());

        // 店铺编号
        String storeNo = null;
        // 店铺昵称
        String storeNickName = null;
        // 商品显示价格
        BigDecimal showTotal = new BigDecimal("0");
        // 商品总价
        BigDecimal pri = new BigDecimal("0");
        // 订单参数
        List<OrderGoodsParam> param = orderStoreParam.getOrderGoodsParams();
        // 要添加的商品订单数据
        List<OrderGoods> ods = new ArrayList<>();
        // 优惠券使用的商品
        Map<String, CouponUseGoodsParam> cugps = new HashMap<>();

        // 验证商品参数是否正确
        for (OrderGoodsParam orderGoodsParam : param) {
            GoodSpecs gs = goodSpecsDaoImpl.findById(orderGoodsParam.getGoodSpecsId());
            // 商品数量
            Integer goodNum = orderGoodsParam.getGoodNum();
            // 判断商品规格是否存在
            if (StringUtil.isBlankObject(gs)) {
                ExpUtil.throwEx("商品规格不存在！");
            }
            if (gs.getStatus() == EGeneralStatus.DISABLE.getCode()) {
                ExpUtil.throwEx("商品已禁用！");
            }
            // 判断剩余商品数量是否满足需求
            if (gs.getStock() - goodNum < 0) {
                ExpUtil.throwEx("商品数量不足");
            }

            Goods g = goodsDaoImpl.findById(gs.getGoodId());
            if (StringUtil.isBlankObject(g)) {
                ExpUtil.throwEx("商品不存在！");
            }
            if (g.getStatus() == EGeneralStatus.DISABLE.getCode()) {
                ExpUtil.throwEx("商品已禁用！");
            }
            String goodsNo = g.getNo();
            CouponUseGoodsParam couponUseGoodsParam = cugps.get(goodsNo);
            if (StringUtil.isBlankObject(couponUseGoodsParam)) {
                CouponUseGoodsParam cugp = new CouponUseGoodsParam();
                cugp.setUseGoodsNo(goodsNo);
                cugp.setTotal(g.getPrice());
                cugps.put(goodsNo, cugp);
            } else {
                couponUseGoodsParam.setTotal(couponUseGoodsParam.getTotal().add(g.getPrice()));
            }

            User member = userDao.findById(g.getUserNo());
            if (StringUtil.isBlankObject(storeNo)) {
                storeNo = member.getId();
                storeNickName = member.getNickName();
                order.setMerchantNo(storeNo);
                order.setMerchantNickName(storeNickName);
            } else {
                if (!storeNo.equals(member.getId())) {
                    ExpUtil.throwEx("所有商品必须是同一个店铺的");
                }
            }

            // 计算价格
            // 商品原价
            // BigDecimal originalPrice = gs.getPrice();
            // 商品单价
            BigDecimal p = gs.getPrice();
            // 此规格商品总价
            BigDecimal multiply = p.multiply(new BigDecimal(String.valueOf(goodNum)));
            // 订单显示价格累计
            // showTotal = showTotal.add(originalPrice.multiply(new BigDecimal(String.valueOf(goodNum))));
            // 订单总价累计
            pri = pri.add(multiply);

            // 添加商品订单数据
            OrderGoods orderGoods = new OrderGoods();
            orderGoods.insertInit();
            orderGoods.setGoodsId(g.getId());
            orderGoods.setGoodName(g.getGoodName());
            orderGoods.setOrderNo(order.getNo());
            orderGoods.setThumb(g.getThumb());
            orderGoods.setNum(goodNum);
            orderGoods.setSpecsId(gs.getId());
            orderGoods.setSpecsName(gs.getName());
            // orderGoods.setOriginalPrice(originalPrice);
            orderGoods.setPrice(p);
            orderGoods.setAllTotal(multiply);
            ods.add(orderGoods);
        }

        // 使用优惠券
        Collection<CouponUseGoodsParam> values = cugps.values();
        List<CouponUseGoodsParam> CouponUseGoodsParams = new ArrayList<>();
        for (CouponUseGoodsParam couponUseGoodsParam : values) {
            CouponUseGoodsParams.add(couponUseGoodsParam);
        }
        CouponUseResponse orderUse =
            couponService.orderUse(couponNos, EModuleNo.SHOPPING_MALL.getCode(), storeNo, CouponUseGoodsParams, pri);
        order.setOrderTotal(orderUse.getTotal());
        order.setCouponNos(orderUse.getCouponNos());
        order.setCouponTotalSplit(orderUse.getTotalSplit());

        // 计算详细价格
        int totalLen = pri.toString().length();
        // 优惠了多少钱
        BigDecimal subBig = ArithUtil.subBig(pri, order.getOrderTotal());
        order.setCouponTotal(subBig);
        order.setShowTotal(showTotal);
        order.setOriginalPrice(pri);
        if (subBig.doubleValue() > 0) {
            BigDecimal sum = pri;
            for (OrderGoods orderGoods : ods) {
                // 商品占价格的百分比
                BigDecimal divRoundDown = ArithUtil.divRoundDown(orderGoods.getAllTotal(), pri, totalLen);
                // 计算优惠价格
                BigDecimal mulRoundDown = ArithUtil.mulRoundDown(divRoundDown, subBig, 2);
                sum = ArithUtil.subBig(sum, mulRoundDown);
                // 判断优惠后是否小于0
                if (sum.doubleValue() < 0) {
                    orderGoods.setCouponTotalRear(new BigDecimal("0"));
                } else {
                    orderGoods.setCouponTotalRear(ArithUtil.subBig(orderGoods.getAllTotal(), mulRoundDown));
                }
            }
        } else {
            for (OrderGoods orderGoods : ods) {
                orderGoods.setCouponTotalRear(orderGoods.getAllTotal());
            }
        }

        // 添加订单
        int insert = orderDaoImpl.insert(order);
        if (insert < 1) {
            ExpUtil.throwEx("添加订单信息失败，请重试！");
        }

        int insertList = orderGoodsDaoImpl.insertList(ods);
        if (insertList != ods.size()) {
            ExpUtil.throwEx("添加订单商品信息失败，请重试！");
        }
        return uuid;
    }

    /**
     * 下单(新签)
     *
     * @param orderParam
     * @return
     * @throws Exception
     */
    @Override
    public int ordersNew(OrderParam orderParam) throws Exception {
        synchronized (Lock.ORDER_STATUS) {
            return orderService.ordersNewGo(orderParam);
        }
    }

    @Transactional(rollbackFor = Throwable.class)
    public int ordersNewGo(OrderParam orderParam) throws Exception {
        int insert = 0;
        return insert;
    }

    /**
     * 下单(续签)
     *
     * @param order
     * @return
     * @throws Exception
     */
    @Override
    public PayResult ordersGoOn(Order order) throws Exception {
        synchronized (Lock.ORDER_STATUS) {
            return orderService.ordersGoOnGo(order);
        }
    }

    @Transactional(rollbackFor = Throwable.class)
    public PayResult ordersGoOnGo(Order order) throws Exception {
        // 订单ID
        String id = order.getId();
        // 获取第一次的订单
        Order findById = orderDaoImpl.findById(id);
        if (StringUtil.isBlankObject(findById)) {
            ExpUtil.throwEx("订单不存在！");
        }
        // 判断是否允许续租
        if (findById.getOrderType() != EOrderType.NEW.getCode()) {
            ExpUtil.throwEx("商品已购买，不需要续租！");
        }
        if (findById.getStatus() != EOrderStatus.RETU_NO.getCode()
            && findById.getStatus() != EOrderStatus.SEND_OUT_YES.getCode()) {
            ExpUtil.throwEx("订单状态不是待收货和待归还！");
        }
        // 租赁天数
        Integer rentDays = order.getRentDays();
        // 优惠券ID
        String couponNos = order.getCouponNos();

        OrderChild orderChild = new OrderChild();
        orderChild.insertInit();
        orderChild.setOrderChildSn(IdUtil.uuid());
        orderChild.setOrderId(id);
        orderChild.setCouponNos(order.getCouponNos());
        orderChild.setOrderType(EOrderType.GO_ON.getCode());
        orderChild.setRentDays(rentDays);

        OrderGoods findByOrderId = orderGoodsDaoImpl.findByOrderNo(couponNos);
        // 数量
        Integer num = findByOrderId.getNum();
        // 单价
        BigDecimal price = findByOrderId.getPrice();
        // 商品总价
        BigDecimal pri = new BigDecimal(Integer.toString(num * rentDays));
        pri = pri.multiply(price);

        orderChild.setOriginalPrice(pri);
        // 判断是否需要使用优惠券
        CouponUseResponse orderUse = couponService.orderUse(couponNos, EModuleNo.SHOPPING_MALL.getCode(),
            findById.getUserNo(), findById.getNo(), pri);
        order.setOrderTotal(orderUse.getTotal());
        order.setCouponNos(orderUse.getCouponNos());
        order.setCouponTotalSplit(orderUse.getTotalSplit());

        orderChild.setCouponNos(couponNos);
        orderChild.setOrderTotal(pri);
        int insert = orderChildDaoImpl.insert(orderChild);
        if (insert < 1) {
            ExpUtil.throwEx("子订单添加失败！");
        }
        // 获取微信接口参数
        Map<String, ConfigVo> config = SystemParamUtil.gets();
        String mchid = config.get(WxConstant.MCHID_CACHE_NAME).getVal();
        String appid = config.get(WxConstant.DEFAULT_APPID_CACHE_NAME).getVal();
        String serialNo = config.get(WxConstant.CA_SERIALNO_CACHE_NAME).getVal();

        // 拼装参数
        WxPamAmount wxPamAmount = new WxPamAmount();
        wxPamAmount.setTotal(ArithUtil.bigDollarToIntPenny(orderChild.getOrderTotal()));
        WxParamV3 wxParam = new WxParamV3();
        wxParam.setAmount(wxPamAmount);
        wxParam.setMchid(mchid);
        wxParam.setNotifyUrl(IpConfig.getUrl() + WxConstant.NOTIFY_URL_PAY_GO_ON);
        wxParam.setAppid(appid);
        wxParam.setOutTradeNo(orderChild.getOrderChildSn());
        wxParam.setDescription(config.get(ConstantCache.WEB_NAME).getVal());
        // 调起微信支付
        IJPayHttpResponse v3 = WxPayApi.v3(RequestMethod.POST, WxDomain.CHINA.getType(), WxApiType.APP_PAY.getType(),
            mchid, serialNo, null, WxUtil.PRIVATE_KEY, JsonUtil.objectToJson(wxParam));
        String body = v3.getBody();
        if (StringUtil.isBlankObject(body)) {
            ExpUtil.throwEx("调用微信统一支付接口失败！");
        }
        // 获取结果
        WxResponseV3 parseObject = JSONObject.parseObject(body, WxResponseV3.class);

        if (StringUtil.isNotBlank(parseObject.getCode())) {
            ExpUtil.throwEx(parseObject.getMessage());
        }

        // 返回结果
        WxResult wxResult = new WxResult();
        wxResult.initXcx(appid, parseObject.getPrepayId());
        return wxResult;
    }

    /**
     * 获取订单信息(包含其他附加信息)
     *
     * @param id
     * @return
     */
    @Override
    public Order getInfo(String id) {
        return orderDaoImpl.getInfo(id);
    }

    /**
     * 根据对象查询
     *
     * @param order
     * @return
     */
    @Override
    public List<OrderVo> list(OrderVo order) {
        return orderDaoImpl.list(order);
    }

    /**
     * 通过订单号获取订单
     *
     * @param no
     * @return
     */
    @Override
    public Order findByNo(String no) {
        return orderDaoImpl.findByNo(no);
    }

    /**
     * 通过订单号数组获取订单
     *
     * @param nos
     * @return
     */
    @Override
    public List<Order> findByNoArr(String[] nos) {
        return orderDaoImpl.findByNoArr(nos);
    }

    /**
     * 通过购物车订单号获取订单
     *
     * @param noShop
     * @return
     */
    @Override
    public List<Order> findByNoShop(String noShop) {
        return orderDaoImpl.findByNoShop(noShop);
    }

    /**
     * 取消订单
     *
     * @param no 订单编号
     * @return
     * @throws Exception
     */
    @Override
    public int cancel(String no) throws Exception {
        synchronized (Lock.ORDER_STATUS) {
            return orderService.cancelGo(no);
        }
    }

    @Transactional(rollbackFor = Throwable.class)
    public int cancelGo(String no) throws Exception {
        int updatePartialById = 0;
        // 查询订单
        Order findByNo = orderDaoImpl.findByNo(no);

        // 查看订单是否存在
        if (StringUtil.isBlankObject(findByNo)) {
            ExpUtil.throwEx("订单不存在！");
        }

        Integer status = findByNo.getStatus();
        // 查看订单是否可以取消
        if (EOrderStatus.PAYMENT_NO.getCode() != status && EOrderStatus.PAYMENT_YES.getCode() != status
            && EOrderStatus.SEND_OUT_NO.getCode() != status && EOrderStatus.SEND_OUT_YES.getCode() != status) {
            ExpUtil.throwEx("订单已完成！");
        }

        // 修改订单状态
        Order ord = new Order();
        // 如果已发货就让商家审核
        if (status == EOrderStatus.SEND_OUT_YES.getCode()) {
            if (findByNo.getSendTime().getTime() + Constant.ORDER_SIGN_FOR_TIME < DateUtil.nowLong()) {
                ExpUtil.throwEx("取消时间已过,系统将在每日0点自动签收已超时已发货的订单！");
            }
            ord.setStatus(EOrderStatus.CANCEL_ING.getCode());
        } else if (findByNo.getIsPay() == EPayStatus.YES.getCode()) {
            // 如果已支付就将状态改为退款中
            ord.setStatus(EOrderStatus.REFUND_ING.getCode());
            ord.setCloseType(EOrderCloseType.CANCEL.getCode());
            ord.setRefundSn(IdUtil.uuid());
            ord.setIsRefunds(ERefundsStatus.ING.getCode());
            ord.setRefundTotal(findByNo.getOrderTotal());
        } else {
            // 如果未支付就将状态改为已关闭
            ord.setStatus(EOrderStatus.CLOSE_YES.getCode());
            ord.setCloseType(EOrderCloseType.CANCEL.getCode());
        }
        ord.setId(findByNo.getId());
        updatePartialById = orderDaoImpl.updatePartialById(ord);
        if (updatePartialById < 1) {
            ExpUtil.throwEx("订单状态修改失败！");
        }

        // 获取优惠券ID
        String couponNos = findByNo.getCouponNos();
        // 如果未付款并且有用优惠券就将优惠券退回
        if (EPayStatus.NO.getCode() == findByNo.getIsPay() && StringUtil.isNotBlankObject(couponNos)) {
            String[] split = couponNos.split(",");
            UserCoupon userCoupon = new UserCoupon();
            userCoupon.setNos(Arrays.asList(split));
            userCoupon.setStatus(EUserCouponStatus.USE_NO.getCode());
            userCouponDaoImpl.updateByNoList(userCoupon);
        }

        // 如果未发货并且已支付就退款
        // 如果已付款就退款
        if (EPayStatus.YES.getCode() == findByNo.getIsPay() && status != EOrderStatus.SEND_OUT_YES.getCode()) {
            ord.refundInit(findByNo.getNo(), findByNo.getOrderTotal(), ord.getRefundSn(), ord.getRefundTotal(),
                findByNo.getPayType());
            PayUtil.refund(ord, IpConfig.getUrl() + WxConstant.NOTIFY_URL_GOODS_CANCEL);
        }

        return updatePartialById;
    }

    // @Transactional(rollbackFor = Throwable.class)
    // public int cancelGo(String no) throws Exception {
    // // TODO
    // int updatePartialById = 0;
    // // 查询订单
    // Order findByNo = orderDaoImpl.findByNo(no);
    //
    // // 查看订单是否存在
    // if (StringUtil.isBlankObject(findByNo)) {
    // ExpUtil.throwEx("订单不存在！");
    // }
    //
    // // 查看订单是否可以取消
    // if (EOrderStatus.PAYMENT_NO.getCode() != findByNo.getStatus()
    // && EOrderStatus.PAYMENT_YES.getCode() != findByNo.getStatus()
    // && EOrderStatus.SEND_OUT_NO.getCode() != findByNo.getStatus()) {
    // ExpUtil.throwEx("订单状态不是待付款和待发货！");
    // }
    //
    // // 修改订单状态
    // Order ord = new Order();
    // // 如果已付款就退款
    // if (EPayStatus.YES.getCode() == findByNo.getIsPay()) {
    // ord.setStatus(EOrderStatus.CANCEL_ING.getCode());
    // } else {
    // ord.setStatus(EOrderStatus.CLOSE_YES.getCode());
    // ord.setCloseType(EOrderCloseType.CANCEL.getCode());
    // }
    // ord.setId(findByNo.getId());
    // updatePartialById = orderDaoImpl.updatePartialById(ord);
    // if (updatePartialById < 1) {
    // ExpUtil.throwEx("订单状态修改失败！");
    // }
    //
    // // 获取优惠券ID
    // String couponNos = findByNo.getCouponNos();
    // // 如果未付款并且有用优惠券就将优惠券退回
    // if (EPayStatus.NO.getCode() == findByNo.getIsPay() && StringUtil.isNotBlankObject(couponNos)) {
    // String[] split = couponNos.split(",");
    // UserCoupon userCoupon = new UserCoupon();
    // userCoupon.setNos(Arrays.asList(split));
    // userCoupon.setStatus(EUserCouponStatus.USE_NO.getCode());
    // userCouponDaoImpl.updateByNoList(userCoupon);
    // }
    //
    // return updatePartialById;
    // }

    /**
     * 发货
     *
     * @param order
     * @return
     * @throws Exception
     */
    @Override
    public int sendOut(Order order) throws Exception {
        Order findByOrderSn = orderDaoImpl.findByNo(order.getNo());
        if (StringUtil.isBlankObject(findByOrderSn)) {
            ExpUtil.throwEx("订单号不存在！");
        }
        Integer status = findByOrderSn.getStatus();
        if (EOrderStatus.SEND_OUT_NO.getCode() != status && EOrderStatus.SEND_OUT_YES.getCode() != status) {
            ExpUtil.throwEx("订单状态不是待发货！");
        }

        order.setStatus(EOrderStatus.SEND_OUT_YES.getCode());
        order.setSendTime(DateUtil.nowDate());
        int updatePartialByOrderSn = orderDaoImpl.updatePartialByOrderSn(order);

        // 销量增加
        List<OrderGoods> orderGoodss = findByOrderSn.getOrderGoodss();
        ArrayList<String> arrayList = new ArrayList<>();
        for (OrderGoods orderGoods : orderGoodss) {
            if (StringUtil.isNotBlankObject(arrayList)) {
                arrayList.add(orderGoods.getGoodsId());
            }
        }
        ArrayList<Goods> findByIdList = goodsDaoImpl.findByIdList(arrayList);
        if (StringUtil.isNotBlankObject(findByIdList) && findByIdList.size() > 0) {
            for (Goods goods : findByIdList) {
                Goods g = new Goods();
                g.updateInit();
                g.setId(goods.getId());
                g.setSales(goods.getSales() + 1);
                goodsDaoImpl.updatePartialById(g);
            }
        }

        User findById = userDao.findById(findByOrderSn.getUserNo());
        if (StringUtil.isNotBlankObject(findById)) {
            // 发送消息
            messageSystemService.send(
                ConstantMessageSystemTemplate.getOrder(order, orderGoodss, ConstantMessageSystemTemplate.ORDER_SEND),
                EMessageSystemType.ORDER.getCode(), 1, findByOrderSn.getId() + "", findById);
        }
        return updatePartialByOrderSn;
    }

    /**
     * 查询快递信息
     *
     * @param orderId 订单ID
     * @return
     * @throws Exception
     */
    @Override
    public Object findExpress(String orderId) throws Exception {
        Order findById = orderDaoImpl.findById(orderId);
        if (StringUtil.isBlankObject(findById)) {
            ExpUtil.throwEx("订单不存在");
        }
        String expressRentCode = findById.getExpressRentCode();
        String expressRentShipperCode = findById.getExpressRentShipperCode();
        if (StringUtil.isBlankObject(expressRentCode) || StringUtil.isBlankObject(expressRentShipperCode)) {
            return null;
        }

        KdnParam kdnParam = new KdnParam();
        kdnParam.setCustomerName(findById.getExpressRentCustomerName());
        kdnParam.setLogisticCode(expressRentCode);
        kdnParam.setShipperCode(expressRentShipperCode);
        KdnResponse timelyQuery = KdnUtil.timelyQuery(kdnParam);
        return timelyQuery.getTraces();
    }

    /**
     * 查询快递信息(归还信息)
     *
     * @param orderId 订单ID
     * @return
     * @throws Exception
     */
    @Override
    public Object findExpressBack(String orderId) throws Exception {
        Order findById = orderDaoImpl.findById(orderId);
        if (StringUtil.isBlankObject(findById)) {
            ExpUtil.throwEx("订单不存在");
        }
        String expressBackCode = findById.getExpressBackCode();
        String expressBackShipperCode = findById.getExpressBackShipperCode();
        if (StringUtil.isBlankObject(expressBackCode) || StringUtil.isBlankObject(expressBackShipperCode)) {
            return null;
        }

        KdnParam kdnParam = new KdnParam();
        kdnParam.setCustomerName(findById.getExpressBackCustomerName());
        kdnParam.setLogisticCode(expressBackCode);
        kdnParam.setShipperCode(expressBackShipperCode);
        KdnResponse timelyQuery = KdnUtil.timelyQuery(kdnParam);
        return timelyQuery.getTraces();
    }

    /**
     * 签收(购买)
     *
     * @param orderId 订单ID
     * @return
     * @throws Exception
     * @throws SQLException
     */
    @Override
    public int signForBuy(String orderId) throws Exception {
        return orderService.signFor(orderId, EOrderStatus.COMMENT_NO.getCode());
    }

    /**
     * 签收(新签)
     *
     * @param orderId 订单ID
     * @return
     * @throws Exception
     * @throws SQLException
     */
    @Override
    public int signForNew(String orderId) throws Exception {
        return orderService.signFor(orderId, EOrderStatus.RETU_NO.getCode());
    }

    /**
     *
     *
     * @param orderId
     * @param status
     * @return
     * @throws Exception
     */
    public int signFor(String orderId, Integer status) throws Exception {
        synchronized (Lock.ORDER_STATUS) {
            synchronized (Lock.BALANCE_LOG) {
                return orderService.signForGo(orderId, status);
            }
        }
    }

    @Transactional(rollbackFor = Throwable.class)
    public int signForGo(String orderId, Integer status) throws Exception {
        Order findById = orderDaoImpl.findById(orderId);
        if (StringUtil.isBlankObject(findById)) {
            ExpUtil.throwEx("订单不存在！");
        }
        if (EOrderStatus.SEND_OUT_YES.getCode() != findById.getStatus()) {
            ExpUtil.throwEx("订单状态不是待收货！");
        }
        if (findById.getSendTime().getTime() + Constant.ORDER_SIGN_FOR_TIME < DateUtil.nowLong()) {
            ExpUtil.throwEx("订单签收已超时，系统将自动签收，如果未签收请等待！");
        }

        return orderService.signForGo(findById, status);
    }

    /**
     *
     *
     * @param orderId
     * @param status
     * @return
     * @throws Exception
     */
    public int signForTask(String orderId, Integer status) throws Exception {
        synchronized (Lock.ORDER_STATUS) {
            synchronized (Lock.BALANCE_LOG) {
                return orderService.signForGoTask(orderId, status);
            }
        }
    }

    @Transactional(rollbackFor = Throwable.class)
    public int signForGoTask(String orderId, Integer status) throws Exception {
        Order findById = orderDaoImpl.findById(orderId);
        if (StringUtil.isBlankObject(findById)) {
            ExpUtil.throwEx("订单不存在！");
        }
        if (EOrderStatus.SEND_OUT_YES.getCode() != findById.getStatus()) {
            ExpUtil.throwEx("订单状态不是待收货！");
        }

        return orderService.signForGo(findById, status);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public int signForGo(Order findById, Integer status) throws Exception {
        // 如果退款编号不是空就说明后台退过款了
        String refundNo = findById.getRefundSn();
        if (StringUtil.isNotBlankObject(refundNo)) {
            findById.setOrderTotal(ArithUtil.subBig(findById.getOrderTotal(), findById.getRefundTotal()));
        }
        // 修改状态
        Order order = new Order();
        order.updateInit();
        order.setId(findById.getId());
        order.setStatus(status);
        order.setSuccessTime(order.getUpdatedAt());
        int updatePartialById = orderDaoImpl.updatePartialById(order);
        if (updatePartialById < 1) {
            ExpUtil.throwEx("签收失败，订单修改失败，请重试！");
        }

        GoodSpecs goodSpecs = goodSpecsDaoImpl.findById(findById.getGoodSpecsId());
        Goods goods = null;
        StringBuilder mark = new StringBuilder(findById.getNo()).append("-");
        if (StringUtil.isNotBlankObject(goodSpecs)) {
            goods = goodsDaoImpl.findById(goodSpecs.getGoodId());
            if (StringUtil.isNotBlankObject(goods)) {
                mark.append(goods.getGoodName()).append("-");
            }
            mark.append(goodSpecs.getName());
        }
        // 修改销量并给商家结算
        String merchantNo = findById.getMerchantNo();
        User findByNo = userDao.findById(merchantNo);
        if (StringUtil.isNotBlankObject(findByNo)) {
            User m = new User();
            m.setId(merchantNo);
            m.setSalesVolume(findByNo.getSalesVolume() + orderGoodsService.countNumByOrderNo(findById.getNo()));
            m.setBrokerage(findByNo.getBrokerage().add(findById.getOrderTotal()));
            m.setBrokerageSum(findByNo.getBrokerageSum().add(findById.getOrderTotal()));
            int updatePartialByNo = userDao.updateById(m);
            if (updatePartialByNo < 1) {
                ExpUtil.throwEx("修改佣金失败，请重试！");
            }

            // 添加佣金记录
            BalanceLog balanceLog = new BalanceLog();
            balanceLog.insertInit("收货通知", findByNo.getId(), findById.getOrderTotal(), findByNo.getBrokerage(),
                EBalanceType.SHOPPING.getCode(), null, EBalanceTotalType.BALANCE.getCode(), EBalanceCount.ADD.getCode(),
                findById.getNo(), findById.getNo() + "-佣金到账");
            int insert = balanceLogDaoImpl.insert(balanceLog);
            if (insert < 1) {
                ExpUtil.throwEx("签收失败,添加佣金记录失败！");
            }
            // 发送消息
            OrderGoods orderGoods = new OrderGoods();
            orderGoods.setOrderNo(findById.getNo());
            List<OrderGoods> findByDto = orderGoodsService.findByDto(orderGoods);
            // 发送消息
            messageSystemService.send(
                ConstantMessageSystemTemplate.getOrder(findById, findByDto,
                    ConstantMessageSystemTemplate.ORDER_SIGN_FOR),
                EMessageSystemType.ORDER.getCode(), 1, findById.getId() + "", findByNo);
        }

        // 添加分成
        Brokerage info = brokerageService.getInfo();
        if (info.getStatus() != EGeneralStatus.NORMAL.getCode()) {
            return updatePartialById;
        }
        // 获取购买用户的上级用户
        User top = userDao.findTopByNo(findById.getUserNo());
        if (StringUtil.isBlankObject(top) || StringUtil.isNotBlankObject(top.getFirstOrderNo())) {
            return updatePartialById;
        }

        // 计算佣金
        // 佣金
        BigDecimal price = null;
        if (info.getType() == 1) {
            price = info.getTotal();
        } else if (info.getType() == 2) {
            // 订单金额
            BigDecimal orderTotal = findById.getOrderTotal();
            // 分佣百分比上限
            BigDecimal totalTop = info.getTotalTop();
            price = ArithUtil.mulRoundDown(info.getTotal(), orderTotal, 2);
            double doubleValue = price.doubleValue();
            if (doubleValue > totalTop.doubleValue()) {
                price = totalTop;
            }
        }
        if (price.doubleValue() <= 0) {
            return updatePartialById;
        }
        // 修改佣金
        BigDecimal add = top.getBalance().add(price);
        User member = new User();
        member.setId(top.getId());
        member.setFirstOrderNo(findById.getNo());
        member.setFirstOrderType(EFirstOrderType.SHOPPING_MALL.getCode());
        member.setBalance(add);
        member.setBalanceSum(top.getBalanceSum().add(price));
        int updateMember = userDao.updateById(member);
        if (updateMember < 1) {
            ExpUtil.throwEx("签收失败,上级用户添加分成失败！");
        }

        // 添加佣金记录
        BalanceLog balanceLog = new BalanceLog();
        balanceLog.insertInit("分销到账", top.getId(), price, top.getBalance(), EBalanceType.DIVIDE.getCode(),
            EBalanceDivideType.SHOPPING.getCode(), EBalanceTotalType.COMMISSION.getCode(), EBalanceCount.ADD.getCode(),
            findById.getNo(), findById.getNo() + "-收货通知");
        balanceLog.setOrderNo(findById.getNo());
        balanceLog.setMark(mark.toString());
        int insert = balanceLogDaoImpl.insert(balanceLog);
        if (insert < 1) {
            ExpUtil.throwEx("签收失败,上级用户添加分成失败！");
        }
        // 发送消息
        messageSystemService.send(ConstantMessageSystemTemplate.getBalanceAccount(price, balanceLog.getCreatedAt()),
            EMessageSystemType.BALANCE.getCode(), EBalanceTotalType.COMMISSION.getCode(), balanceLog.getId() + "", top);

        return updatePartialById;
    }

    /**
     * 签收(归还)
     *
     * @param orderId 订单ID
     * @return
     * @throws SQLException
     */
    @Override
    public int signForReturn(String orderId) {
        Order findById = orderDaoImpl.findById(orderId);
        if (StringUtil.isBlankObject(findById)) {
            ExpUtil.throwEx("订单不存在！");
        }
        if (EOrderStatus.RETU_ING.getCode() != findById.getStatus()) {
            ExpUtil.throwEx("订单状态不是归还中！");
        }

        // 修改状态
        Order order = new Order();
        order.setId(findById.getId());
        order.setStatus(EOrderStatus.RETU_YES.getCode());
        return orderDaoImpl.updatePartialById(order);
    }

    /**
     * 获取订单信息(包含其他附加信息)
     *
     * @param orderSn 订单编号
     * @return
     */
    @Override
    public Order getInfoByOrderSn(String orderSn) {
        return orderDaoImpl.getInfoByOrderSn(orderSn);
    }

    /**
     * 获取购物车订单信息(包含其他附加信息)
     *
     * @param noShop 购物车订单编号
     * @return
     */
    @Override
    public List<Order> getInfoByNoShop(String noShop) {
        return orderDaoImpl.getInfoByNoShop(noShop);
    }

    /**
     * 归还
     *
     * @param orderId 订单ID
     * @return
     * @throws Exception
     */
    @Override
    public int returnSendOut(Order order) throws Exception {
        Order findByOrderSn = orderDaoImpl.findByNo(order.getNo());
        if (StringUtil.isBlankObject(findByOrderSn)) {
            ExpUtil.throwEx("订单号不存在！");
        }
        Integer status = findByOrderSn.getStatus();
        if (EOrderStatus.RETU_NO.getCode() != status) {
            ExpUtil.throwEx("订单状态不是待归还！");
        }

        order.setStatus(EOrderStatus.RETU_ING.getCode());
        return orderDaoImpl.updatePartialByOrderSn(order);
    }

    /**
     * 租赁退款
     *
     * @param order
     * @return
     * @throws Exception
     */
    @Override
    public int refundNew(OrderVo order) throws Exception {
        synchronized (Lock.ORDER_STATUS) {
            return orderService.refundNewGo(order);
        }
    }

    @Transactional(rollbackFor = Throwable.class)
    public int refundNewGo(OrderVo order) throws Exception {
        int updatePartialById = 0;
        Order findByOrderSn = orderDaoImpl.findByNo(order.getNo());
        if (StringUtil.isBlankObject(findByOrderSn)) {
            ExpUtil.throwEx("订单不存在！");
        }
        if (findByOrderSn.getIsPay() == EPayStatus.YES.getCode()) {
            if (findByOrderSn.getOrderTotal().subtract(order.getOrderTotal()).doubleValue() < 0) {
                ExpUtil.throwEx("订单退款金额大于订单金额！");
            }
            Integer isRefunds = findByOrderSn.getIsRefunds();
            if (isRefunds == ERefundsStatus.YES.getCode() || isRefunds == ERefundsStatus.ING.getCode()) {
                ExpUtil.throwEx("一个订单只能退款一次！");
            }
        }
        Order ord = new Order();
        ord.updateInit();
        ord.setId(findByOrderSn.getId());
        ord.setStatus(EOrderStatus.RETU_YES.getCode());
        ord.setRefundTotal(order.getOrderTotal());
        ord.setIsRefunds(ERefundsStatus.ING.getCode());
        updatePartialById = orderDaoImpl.updatePartialById(ord);
        // 关闭订单
        if (updatePartialById < 1) {
            ExpUtil.throwEx("关闭订单失败！");
        }
        if (findByOrderSn.getIsPay() == EPayStatus.NO.getCode()) {
            return 1;
        }
        // 获取微信接口参数
        Map<String, ConfigVo> config = SystemParamUtil.gets();
        String mchid = config.get(WxConstant.MCHID_CACHE_NAME).getVal();
        String serialNo = config.get(WxConstant.CA_SERIALNO_CACHE_NAME).getVal();

        // 拼装参数
        WxPamAmount wxPamAmount = new WxPamAmount();
        wxPamAmount.setCurrency(WxCurrencyType.CNY);
        wxPamAmount.setRefund(ArithUtil.bigDollarToIntPenny(ord.getRefundTotal()));
        wxPamAmount.setTotal(ArithUtil.bigDollarToIntPenny(findByOrderSn.getOrderTotal()));
        WxParamV3 wxParam = new WxParamV3();
        wxParam.setAmount(wxPamAmount);
        wxParam.setNotifyUrl(IpConfig.getUrl() + WxConstant.NOTIFY_URL_PAY_CANCEL_INITIATIVE);
        wxParam.setOutRefundNo(IdUtil.uuid());
        wxParam.setOutTradeNo(findByOrderSn.getNo());
        // 调用退款接口
        IJPayHttpResponse v3 =
            WxPayApi.v3(RequestMethod.POST, WxDomain.CHINA.getType(), WxApiType.DOMESTIC_REFUNDS.getType(), mchid,
                serialNo, null, WxUtil.PRIVATE_KEY, JsonUtil.objectToJson(wxParam));
        // 获取响应结果
        WxResponseV3 jsonToObject = JsonUtil.jsonToObject(v3.getBody(), WxResponseV3.class);
        String status = jsonToObject.getRefundStatus();
        if (!"SUCCESS".equals(status) && !"PROCESSING".equals(status)) {
            ExpUtil.throwEx("退款失败" + jsonToObject.getMessage());
        }
        return updatePartialById;
    }

    /**
     * 定时任务自动关闭订单
     *
     * @param nowDate
     * @return
     */
    @Override
    public int cancelAuto(Date nowDate) {
        return orderDaoImpl.cancelAuto(nowDate);
    }

    /**
     * 申请取消订单审核
     *
     * @param order 订单
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public int cancelAudit(OrderVo o) throws Exception {
        synchronized (Lock.ORDER_STATUS) {
            return cancelAuditGo(o);
        }
    }

    @Transactional(rollbackFor = Throwable.class)
    public int cancelAuditGo(OrderVo ord) throws Exception {
        // 修改订单
        Order findById = orderDaoImpl.findById(ord.getId());
        if (StringUtil.isBlankObject(findById)) {
            ExpUtil.throwEx("订单不存在！");
        }
        if (findById.getStatus() != EOrderStatus.CANCEL_ING.getCode()) {
            ExpUtil.throwEx("订单不需要审核！");
        }
        Boolean cancelAudit = ord.getCancelAudit();
        // 如果不同意就将状态改为待收货
        if (!cancelAudit) {
            ord.setStatus(EOrderStatus.SEND_OUT_YES.getCode());
            int updatePartialById = orderDaoImpl.updatePartialById(ord);
            return updatePartialById;
        }

        // 如果同意就退款
        // 修改订单状态
        ord.setRefundSn(IdUtil.uuid());
        ord.setRefundTotal(findById.getOrderTotal());
        ord.setIsRefunds(ERefundsStatus.ING.getCode());
        ord.setStatus(EOrderStatus.REFUND_ING.getCode());
        ord.setCloseType(EOrderCloseType.CANCEL.getCode());
        int updatePartialById = orderDaoImpl.updatePartialById(ord);

        ord.refundInit(findById.getNo(), findById.getOrderTotal(), ord.getRefundSn(), ord.getRefundTotal(),
            findById.getPayType());
        PayUtil.refund(ord, IpConfig.getUrl() + WxConstant.NOTIFY_URL_GOODS_CANCEL);

        return updatePartialById;
    }

    /**
     * 查询订单列表
     *
     * @param orderVo
     * @return
     */
    @Override
    public List<OrderVo> findByVO(OrderVo orderVo) {
        return orderDaoImpl.findByVO(orderVo);
    }

    /**
     * 查询订单ID列表
     *
     * @param orderVo
     * @return
     */
    @Override
    public List<String> findIdsByVO(OrderVo orderVo) {
        return orderDaoImpl.findIdsByVO(orderVo);
    }

    /**
     * 后台订单退款
     *
     * @param order 订单
     * @return
     * @throws Exception
     */
    @Override
    public int refund(OrderVo o) throws Exception {
        synchronized (Lock.ORDER_STATUS) {
            synchronized (Lock.BALANCE_LOG) {
                return refundGo(o);
            }
        }
    }

    @Transactional(rollbackFor = Throwable.class)
    public int refundGo(OrderVo ord) throws Exception {
        Order findById = orderDaoImpl.findById(ord.getId());

        if (StringUtil.isBlankObject(findById)) {
            ExpUtil.throwEx("订单不存在！");
        }
        Integer status = findById.getStatus();
        if (status != EOrderStatus.SEND_OUT_YES.getCode() && status != EOrderStatus.CANCEL_ING.getCode()) {
            ExpUtil.throwEx("只能处理待收货的订单，未发货的用户可以手动取消，已收货的请线下结算！");
        }
        Date sendTime = findById.getSendTime();
        if (sendTime.getTime() + Constant.ORDER_SIGN_FOR_TIME < DateUtil.nowLong()) {
            ExpUtil.throwEx("退款时间已过,系统将在每日0点自动签收已超时已发货的订单！");
        }
        if (StringUtil.isNotBlankObject(findById.getRefundSn())) {
            ExpUtil.throwEx("此订单已处理过退款，请勿重复操作！");
        }
        ord.setRefundSn(IdUtil.uuid());
        ord.setIsRefunds(ERefundsStatus.ING.getCode());
        ord.setCloseType(EOrderCloseType.REIMBURSE.getCode());
        double refundTotal = ord.getRefundTotal().doubleValue();
        double orderTotal = findById.getOrderTotal().doubleValue();
        if (refundTotal > orderTotal) {
            ExpUtil.throwEx("退款金额不能大于订单支付金额！");
        } else if (refundTotal == orderTotal) {
            ord.setStatus(EOrderStatus.REFUND_ING.getCode());
        } else {
            ord.setStatus(EOrderStatus.SEND_OUT_NO.getCode());
        }
        int updatePartialById = orderDaoImpl.updatePartialById(ord);
        if (updatePartialById < 1) {
            ExpUtil.throwEx("订单状态修改失败！");
        }
        // 如果没有退完就签收
        if (ord.getStatus() == EOrderStatus.SEND_OUT_NO.getCode()) {
            orderService.signForGo(findById, EOrderStatus.COMMENT_NO.getCode());
        }

        ord.refundInit(findById.getNo(), findById.getOrderTotal(), ord.getRefundSn(), ord.getRefundTotal(),
            findById.getPayType());
        PayUtil.refund(ord, IpConfig.getUrl() + WxConstant.NOTIFY_URL_GOODS_CANCEL);
        return updatePartialById;
    }

    /**
     * 商家首页统计
     *
     * @return
     */
    @Override
    public Map<String, Integer> count(OrderVo order) {
        return orderDaoImpl.count(order);
    }

    /**
     * 用户首页统计
     *
     * @return
     */
    @Override
    public Map<String, Integer> countUser(OrderVo order) {
        return orderDaoImpl.countUser(order);
    }

}